import message from '@/utils/message'
import Settings from '@/config/settings'
import I18n from '@/config/i18n'
import { useGlobalStore } from '@/stores/global'
import LocalStorage from '@/utils/localstorage'
import Constants from '@/utils/constants'

class Functions {
    static timer = null
    static duration = 1500
    //调用的函数需带有success、fail参数，否则结果不可预期
    static promise(func : any) {
        return function (params = {}) {
            return new Promise((resolve, reject) => {
                try {
                    const args = Object.assign(params, {
                        success: (res : any) => {
                            resolve(res);
                        },
                        fail: (error : any) => {
                            reject(error);
                        }
                    });
                    func(args);
                } catch (err) {
                    reject(err)
                }
            });
        };
    }
    //提示框
    static showToast(options : UniApp.ShowToastOptions, sync : boolean = false) {
        const params = {
            title: options?.title || '加载中...',
            icon: options?.icon || 'none',
            image: options?.image || '',
            duration: options?.duration || Functions.duration,
            position: options?.position || undefined,
            mask: options?.mask === false ? false : true,
            //异步(Promise)无法设置匿名函数，用await获取结果
            success: options?.success || function () { },
            fail: options?.fail || function () { },
            complete: options?.complete || function () { }
        }
        if (sync) {
            return Functions.promise(uni.showToast)(params)
        } else {
            return uni.showToast(params)
        }
    }
    //模态弹窗
    static showModal(options : UniApp.ShowModalOptions, sync : boolean = false) {
        const params = {
            title: options?.title || '提示',
            content: options?.content || '',
            showCancel: options?.showCancel === false ? false : true,
            cancelText: options?.cancelText || '取消',
            cancelColor: options?.cancelColor || "#000000",
            confirmText: options?.confirmText || '确定',
            confirmColor: options?.confirmColor || "#576B95",
            editable: Boolean(options?.editable),
            placeholderText: options?.placeholderText || '',
            //异步(Promise)无法设置匿名函数，用await获取结果
            success: options?.success || function () { },
            fail: options?.fail || function () { },
            complete: options?.complete || function () { }
        }
        if (sync) {
            return Functions.promise(uni.showModal)(params)
        } else {
            return uni.showModal(params)
        }
    }

    static showModalSync(options : UniApp.ShowModalOptions) {
        return Functions.showModal(options, true)
    }
    //模拟框提示
    static showModalTip(options : UniApp.ShowModalOptions, sync : boolean = false) {
        return Functions.showModal({ ...options, showCancel: false }, sync)
    }
    //加载框
    static showLoading(options : UniApp.ShowLoadingOptions = {}, sync : boolean = false) {
        const params = {
            title: options?.title || '加载中...',
            mask: options?.mask === false ? false : true,
            //异步(Promise)无法设置匿名函数，用await获取结果
            success: options?.success || function () { },
            fail: options?.fail || function () { },
            complete: options?.complete || function () { }
        }
        if (sync) {
            return Functions.promise(uni.showLoading)(params)
        } else {
            return uni.showLoading(params)
        }
    }
    //关闭加载框
    static hideLoading() {
        return uni.hideLoading()
    }
    //路由跳转
    static navigateTo(options : UniApp.NavigateToOptions, sync : boolean = false) {
        if (!options?.url) {
            return false
        }
        const params = {
            url: options?.url,
            animationType: options?.animationType || 'pop-in',
            animationDuration: options?.animationDuration || 300,
            events: options?.events || {},
            //异步(Promise)无法设置匿名函数，用await获取结果
            success: options?.success || function () { },
            fail: options?.fail || function () { },
            complete: options?.complete || function () { }
        }
        if (sync) {
            return Functions.promise(uni.navigateTo)(params)
        } else {
            return uni.navigateTo(params)
        }
    }
    static switchTab(options : UniApp.SwitchTabOptions, sync : boolean = false) {
        if (!options?.url) {
            return false
        }
        const params = {
            url: options?.url,
            //异步(Promise)无法设置匿名函数，用await获取结果
            success: options?.success || function () { },
            fail: options?.fail || function () { },
            complete: options?.complete || function () { }
        }
        if (sync) {
            return Functions.promise(uni.switchTab)(params)
        } else {
            return uni.switchTab(params)
        }
    }
    //路由关闭跳转
    static redirectTo(options : UniApp.RedirectToOptions, sync : boolean = false) {
        if (!options?.url) {
            return false
        }
        const params = {
            url: options?.url,
            //异步(Promise)无法设置匿名函数，用await获取结果
            success: options?.success || function () { },
            fail: options?.fail || function () { },
            complete: options?.complete || function () { }
        }
        if (sync) {
            return Functions.promise(uni.redirectTo)(params)
        } else {
            return uni.redirectTo(params)
        }
    }

    static reLaunch(options, sync : boolean = true) {
        if (!options?.url) {
            return false
        }
        const params = {
            url: options?.url,
            //异步(Promise)无法设置匿名函数，用await获取结果
            success: options?.success || function () { },
            fail: options?.fail || function () { },
            complete: options?.complete || function () { }
        }
        if (sync) {
            return Functions.promise(uni.reLaunch)(params)
        } else {
            return uni.reLaunch(params)
        }
    }
    //路由回退
    static navigateBack(options : UniApp.NavigateBackOptions, sync : boolean = false) {
        const params = {
            delta: options?.delta || 1,
            animationType: options?.animationType || 'pop-out',
            animationDuration: options?.animationDuration || 300,
            //异步(Promise)无法设置匿名函数，用await获取结果
            success: options?.success || function () { },
            fail: options?.fail || function () { },
            complete: options?.complete || function () { }
        }
        if (sync) {
            return Functions.promise(uni.navigateBack)(params)
        } else {
            return uni.navigateBack(params)
        }
    }
    static backRefresh() {
        const pages = getCurrentPages()
        if (pages.length > 1) {
            const page = pages[pages.length - 2]
            page?.$vm?.$?.exposed?.onrefresh()
        }
    }
    //消息翻译（不是语言翻译）
    static trans(key : string | number, defaultVal : string = '') {
        if (Object.hasOwn(message, key)) {
            return message[key]
        }
        return defaultVal
    }
    //防抖动，应在注释回调时返回函数
    static debounce(callback : any) {
        if (Functions.timer) {
            clearTimeout(Functions.timer)
        }
        Functions.timer = setTimeout(() => {
            callback()
        }, 500)
    }
    // 延迟函数
    static sleep(milliseconds : number) {
        milliseconds = milliseconds || Functions.duration
        return new Promise(resolve => setTimeout(resolve, milliseconds))
    }

    static getUrlParams(search : any) {
        search = decodeURIComponent(search)
        const hashes = search.slice(search.indexOf('?') + 1).split('&')
        const params = {}
        hashes.map(hash => {
            const [key, val] = hash.split('=')
            params[key] = isNaN(val) ? val : +val
        })
        return params
    }

    static alert(error : any, defaultMsg = '') {
        const code = error?.code || ''
        const msg = error?.msg || defaultMsg
        if (!message[code] && msg) {
            Functions.showModalTip({
                content: msg + (/^\d+$/.test(code) ? '[' + code + ']' : '')
            })
        }
    }

    static getImage(path : string) {
        return Settings.storageUrl + path
    }

    static t(key : string) {
        if (I18n.messages[I18n.locale][key]) {
            return I18n.messages[I18n.locale][key]
        }
        return key
    }

    static toast(error : any, defaultMsg = '') {
        const code = error?.code || ''
        const msg = error?.msg || defaultMsg
        if ((!code || !message[code]) && msg) {
            Functions.showToast({
                title: msg + (/^\d+$/.test(code) ? '[' + code + ']' : '')
            })
        }
    }

    static getAuthorization() {
        const headerToken = LocalStorage.getToken()
        const { token, token_type } = headerToken
        return token_type + ' ' + token
    }

    static orderStatusText(type) {
        let text = ''
        type == Constants.TOGO && (text = '打包')
        type == Constants.TAKEOUT && (text = '外卖')
        type == Constants.BOOKING && (text = '预订')
        type == Constants.PAYLATER && (text = '后付款')
        type == Constants.EATIN && (text = '堂食')
        return text
    }

    static printerStatusText(status) {
        switch (+status) {
            case Constants.ONLINE:
                return '在线'
            case Constants.OFFLINE:
                return '离线'
            default:
                return ''
        }
    }

    static access(path) {
        return useGlobalStore().user?.rules?.includes(path)
    }

    /**
     * 对比版本号
     * 支持比对	("3.0.0.0.0.1.0.1", "3.0.0.0.0.1")	("3.0.0.1", "3.0")	("3.1.1", "3.1.1.1") 之类的
     * @param {Object} v1
     * @param {Object} v2
     * v1 > v2 return 1
     * v1 < v2 return -1
     * v1 == v2 return 0
     */
    static versionCompare(v1, v2) {
        try {
            v1 = String(v1 || '0').split('.')
            v2 = String(v2 || '0').split('.')
            const minVersionLens = Math.min(v1.length, v2.length);

            let result = 0;
            for (let i = 0; i < minVersionLens; i++) {
                const curV1 = Number(v1[i])
                const curV2 = Number(v2[i])

                if (curV1 > curV2) {
                    result = 1
                    break;
                } else if (curV1 < curV2) {
                    result = -1
                    break;
                }
            }

            if (result === 0 && (v1.length !== v2.length)) {
                const v1BiggerThenv2 = v1.length > v2.length;
                const maxLensVersion = v1BiggerThenv2 ? v1 : v2;
                for (let i = minVersionLens; i < maxLensVersion.length; i++) {
                    const curVersion = Number(maxLensVersion[i])
                    if (curVersion > 0) {
                        v1BiggerThenv2 ? result = 1 : result = -1
                        break;
                    }
                }
            }
            return result
        } catch (e) {
            console.log(e)
        }
    }

    static proxyEndpoint(obj) {
        return new Proxy(obj, {
            get(target, prop, receiver) {
                return new Proxy(target[prop], {
                    apply(target, thisArg, argArray) {
                        const route = getCurrentPages().pop().route
                        const accessid = (route[0] == '/' ? '' : '/') + route + '/' + target.name.replace(/([A-Z])/g, '/$1').toLowerCase()
                        return target(argArray[0], { accessid: accessid || {} })
                    }
                })
            }
        })
    }

    static getVersion() {
        return new Promise((resolve, reject) => {
            try {
                plus.runtime.getProperty(plus.runtime.appid, data => {
                    const ver = Functions.versionCompare(data.version, plus.runtime.version) > 0 ? data.version : plus.runtime.version
                    const code = Functions.versionCompare(data.versionCode, plus.runtime.versionCode) > 0 ? data.versionCode : plus.runtime.versionCode
                    resolve({ ver, code })
                })
            } catch (err) {
                resolve('')
            }
        })
    }

    static hdError(error, defaultText = '') {
        defaultText = defaultText || 'unknown'
        let code = error?.code || Constants.UNKNOWN
        let msg = error?.text || message[code] || defaultText
        if (msg) {
            Functions.showToast({
                title: msg + (/^\-?\d+$/.test(code) ? '[' + code + ']' : '')
            })
        }
    }

    static convertFenToYuan(fen) {
        if (isNaN(fen)) {
            return 0;
        }
        return (fen / 100).toFixed(2)
    }
}
const getImage = Functions.getImage
const t = Functions.t
export { getImage, t };
export default Functions